package com.crawler.harbour.controller;


import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.crawler.harbour.common.DockCode;
import com.crawler.harbour.common.GJHGCostSpider;
import com.crawler.harbour.dto.CostCode;
import com.crawler.harbour.dto.CostParametersDto;
import com.crawler.harbour.dto.FZdanxiangDto;
import com.crawler.harbour.dto.FZzaigangDto;
import com.crawler.harbour.dto.GGHGbiaozhunDto;
import com.crawler.harbour.dto.HTRTFeeDto;
import com.crawler.harbour.dto.LoginParamsDto;
import com.crawler.harbour.dto.SYTuocheDto;
import com.crawler.harbour.dto.TerminalCostDto;
import com.crawler.harbour.dto.YHJZXbiaozhunDto;
import com.crawler.harbour.exception.SimpleException;
import com.crawler.harbour.model.Danxiang;
import com.crawler.harbour.model.GGHGbiaozhun;
import com.crawler.harbour.model.YHJZXbiaozhun;
import com.crawler.harbour.model.Zaigang;
import com.crawler.harbour.utils.AESUtil;
import com.crawler.harbour.utils.DateUtils;
import com.crawler.harbour.utils.LoginUtil;
import com.crawler.harbour.utils.RuoKuai;
import com.crawler.harbour.utils.StorageDay;
import com.crawler.harbour.utils.UrlUtil;
import com.google.common.collect.Lists;

import net.dongliu.requests.RawResponse;
import net.dongliu.requests.Requests;
import net.dongliu.requests.Response;
import net.dongliu.requests.Session;
/**
 * 费用查询
 * @author czj
 *
 */
@RestController
@RequestMapping(value = "/crawler")
public class CrawlerController extends StorageDay{

	private ExecutorService service =  new ThreadPoolExecutor(6, 30,
            0L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>());

    private static final Logger LOGGER = LoggerFactory.getLogger(CrawlerController.class);

    /**
     *  费用查询接口
     * @param costParametersDtoList
     * @return
     */
    @RequestMapping(value = "terminalCostSelect", method = RequestMethod.POST)
    public Object terminalCostSelect(@RequestBody List<CostParametersDto> costParametersDtoList) {
    	Vector<Object> result = new Vector<>();
    	List<CostParametersDto> _costParametersDtoList = Lists.newArrayList();
    	List<GGHGbiaozhunDto> _gghGbiaozhunDtoList = Lists.newArrayList();
    	List<HTRTFeeDto> _htrtFeeDtoList_HRD = Lists.newArrayList();
    	List<HTRTFeeDto> _htrtFeeDtoList_HTD = Lists.newArrayList();
    	List<SYTuocheDto> _syTuocheDtoList = Lists.newArrayList();
    	List<YHJZXbiaozhunDto> _yhjzXbiaozhunDtoList = Lists.newArrayList();
    	List<TerminalCostDto> _terminalCostDtoList = Lists.newArrayList();
    	buildSearch(costParametersDtoList,
    			_costParametersDtoList,
    			_gghGbiaozhunDtoList,
    			_htrtFeeDtoList_HRD,
    			_htrtFeeDtoList_HTD,
    			_syTuocheDtoList,
    			_yhjzXbiaozhunDtoList,
    			_terminalCostDtoList);
    	
    	CountDownLatch cd =new CountDownLatch(6); 
    	service.execute(new SearchThread<>(_costParametersDtoList, result, 1, cd));
    	service.execute(new SearchThread<>(_gghGbiaozhunDtoList, result, 2, cd));
    	service.execute(new SearchThread<>(_htrtFeeDtoList_HRD, result, 3, cd));
    	service.execute(new SearchThread<>(_htrtFeeDtoList_HTD, result, 4, cd));
    	service.execute(new SearchThread<>(_syTuocheDtoList, result, 5, cd));
    	service.execute(new SearchThread<>(_yhjzXbiaozhunDtoList, result, 6, cd));
    	try {
			cd.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
    	result.addAll(_terminalCostDtoList);	
    	return result;
    }
    
    
    /**
     * 单箱历史追踪
     *
     * @param fZdanxiangDto
     * @return
     */
    @RequestMapping(value = "singleBoxTracking", method = RequestMethod.POST)
    public Object danxiang(@RequestBody FZdanxiangDto fZdanxiangDto) {
        Session session = Requests.session();
        Response<String> index = session.get(UrlUtil.FZdanxiangzhuizong).send().toTextResponse();
        String indexBody = index.getBody();
        Document document = Jsoup.parse(indexBody);
        Element captchaImg = document.getElementById("captchaImg");
        String captchaUrl = captchaImg.attributes().get("src").toString();

        List<Danxiang> danxiangList = new ArrayList<>();
        RawResponse send = session.get("http://www.fzpu.com"+captchaUrl).verify(false).send();
        //解析验证码
        String code = RuoKuai.createByPost(send.readToBytes());
        String captchaCode =null;
        try {
        	captchaCode = JSON.parseObject(code).get("Result").toString();
        }catch (Exception e) {
        	LOGGER.error(e.getMessage(),e);
        	throw new SimpleException("调用验证码识别接口异常");
		}      
        Map<String, Object> param = new HashMap<>();
        param.put("dx", fZdanxiangDto.getContainerNo());
        param.put("currentCategoryId", "4028e48d265a69fe01265a7002f20007");
        param.put("j_captcha", captchaCode);
        param.put("maxRows", "20");
        param.put("op", "");
        param.put("openf", "1");
        param.put("parentCategoryId", "4028e48d2653bc1d012653e154c20002");
        param.put("tj", "");
        param.put("zyq", fZdanxiangDto.getPortNo());
        String dxResult = session.post("http://www.fzpu.com/fzpu2009/site/commonquery/sbhquery.action?op=query&dx=" + fZdanxiangDto.getContainerNo() + "&vzyq=" + fZdanxiangDto.getPortNo()).body(param).send().toTextResponse().getBody();

       
        Document dxDocument = Jsoup.parse(dxResult);
        for (int i = 1; ; i++) {
            Element element = dxDocument.getElementById("dxgzTag_row" + i);
            if (element == null) {
                break;
            }
            Elements elements = element.getElementsByTag("td");
            Danxiang danxiang = new Danxiang();
            danxiang.setVSL(elements.get(0).text());
            danxiang.setVVD(elements.get(1).text());
            danxiang.setLadingBillNo(elements.get(2).text());
            danxiang.setContainerNo(elements.get(3).text());
            danxiang.setEQP_TYPE(elements.get(4).text());
            danxiang.setEQP_COND(elements.get(5).text());
            danxiang.setEQP_STA(elements.get(6).text());
            danxiang.setOPR(elements.get(7).text());
            danxiang.setSEAL(elements.get(8).text());
            danxiang.setTRADE_TYPE(elements.get(9).text());
            danxiang.setLOC(elements.get(10).text());
            danxiang.setTRK_CO(elements.get(11).text());
            danxiang.setTRK(elements.get(12).text());
            danxiang.setACTIVITY(elements.get(13).text());
            danxiang.setLST_TX_DATE(elements.get(14).text());
            danxiangList.add(danxiang);
        }
        return danxiangList;
    }


    /**
     * 在港箱查询
     *
     * @param fZzaigangDto
     * @return
     */
    @RequestMapping(value = "atThePortSearch", method = RequestMethod.POST)
    public Object zaigang(@RequestBody FZzaigangDto fZzaigangDto) {
        Session session = Requests.session();
        Response<String> index = session.get(UrlUtil.FZzaigang).send().toTextResponse();
        String indexBody = index.getBody();
        Document document = Jsoup.parse(indexBody);
        Element captchaImg = document.getElementById("captchaImg");
        String captchaUrl = captchaImg.attributes().get("src").toString();
        RawResponse send = session.get("http://www.fzpu.com"+captchaUrl).verify(false).send();
        //解析验证码
        String code = RuoKuai.createByPost(send.readToBytes());

        String captchaCode = null;
        try {
        	 captchaCode = JSON.parseObject(code).get("Result").toString();
        }catch (Exception e) {
        	LOGGER.error(e.getMessage(),e);
        	throw new SimpleException("调用验证码识别接口异常");
		}
        Map<String, Object> param = new HashMap<>();
        param.put("suitcaseNo", "");
        param.put("cntr", fZzaigangDto.getContainerNo());
        param.put("bl_no", fZzaigangDto.getLadingBillNo());
        param.put("currentCategoryId", "2c90e3852924d397012925d17ff50018");
        param.put("data", "0");
        param.put("j_captcha", captchaCode);
        param.put("maxRows", "200");
        param.put("method", "1");
        param.put("op", "");
        param.put("openf", "0");
        param.put("parentCategoryId", "4028e48d2653bc1d012653e154c20002");
        param.put("tabx", "");
        param.put("tj", fZzaigangDto.getContainerNo() + "~~" + fZzaigangDto.getPortNo());
        param.put("zyq", fZzaigangDto.getPortNo());
        String dxResult = session.post("http://www.fzpu.com/fzpu2009/site/commonquery/waybillquery.action?op=query").body(param).send().toTextResponse().getBody();
        List<Zaigang> zaigangList = new ArrayList<>();
        Document dxDocument = Jsoup.parse(dxResult);
        for (int i = 1; ; i++) {
            Element element = dxDocument.getElementById("tdxxTag_row" + i);
            if (element == null) {
                break;
            }
            Elements elements = element.getElementsByTag("td");
            Zaigang zaigang = new Zaigang();
            zaigang.setVSL(elements.get(0).text());
            zaigang.setVVD(elements.get(1).text());
            zaigang.setLadingBillNo(elements.get(2).text());
            zaigang.setContainerNo(elements.get(3).text());
            zaigang.setEQP_TYPE(elements.get(4).text());
            zaigang.setFe_ind(elements.get(5).text());
            zaigang.setGRS_WGT(elements.get(6).text());
            zaigang.setPOL(elements.get(7).text());
            zaigang.setOPD(elements.get(8).text());
            zaigang.setPOD(elements.get(9).text());
            zaigang.setLOC(elements.get(10).text());
            zaigang.setFXL(elements.get(11).text());
            zaigang.setSEAL(elements.get(12).text());
            zaigang.setLOCKED(elements.get(13).text());
            zaigang.setENTRY_DATE(elements.get(14).text());
            zaigangList.add(zaigang);
        }
        return zaigangList;
    }

    /**
     * 厦门国际货柜码头标准费用查询
     *
     * @param gghGbiaozhunDto
     * @return
     */
    private List<Object> GGHGbiaozhun(List<GGHGbiaozhunDto> gghGbiaozhunDtoList) {    	
    	List<Object> result = Lists.newArrayList();
    	if(gghGbiaozhunDtoList.isEmpty()) {
			return result;
		}
        Session session = Requests.session();
        for(GGHGbiaozhunDto gghGbiaozhunDto: gghGbiaozhunDtoList) {
        	Map<String, Object> param = new HashMap<>();
	        param.put("actionUrl", "this");
	        param.put("blNo", gghGbiaozhunDto.getLadingBillNo());
	        param.put("containerId", gghGbiaozhunDto.getContainerNo());
	        param.put("submit", "查询");
	        param.put("voyage", "");
	        String dxResult = session.post(UrlUtil.GGHGBIAOZHUN).body(param).send().toTextResponse().getBody();
	        Document dxDocument = Jsoup.parse(dxResult);
	        Elements table = dxDocument.getElementsByClass("quotation_size");
	        Elements tr = table.get(0).getElementsByTag("tr");
	        String dataHeader = tr.get(0).text();
	        System.out.println(dataHeader);   
	        GGHGbiaozhun gghGbiaozhun = null;
	        for (int i = 2; i < tr.size(); i++) {
	            Elements elements = tr.get(i).getElementsByTag("td");
	            gghGbiaozhun = new GGHGbiaozhun();
//	            gghGbiaozhun.setXu(elements.get(0).text());
	            gghGbiaozhun.setId(gghGbiaozhunDto.getId());
	            gghGbiaozhun.setLadingBillNo(elements.get(1).text());
	            gghGbiaozhun.setContainerNo(elements.get(2).text());
//	            gghGbiaozhun.setChima(elements.get(3).text());
	            gghGbiaozhun.setTotalFee(elements.get(4).text());
	            gghGbiaozhun.addFee(CostCode._300001, elements.get(5).text());
	            gghGbiaozhun.addFee(CostCode._300002, elements.get(6).text());
	            gghGbiaozhun.addFee(CostCode._300003, elements.get(7).text());
	            gghGbiaozhun.addFee(CostCode._300004, elements.get(8).text());
	            gghGbiaozhun.addFee(CostCode._300027, elements.get(9).text());
	            gghGbiaozhun.addFee(CostCode._300010, elements.get(10).text());
	            gghGbiaozhun.addFee(CostCode._300012, elements.get(11).text());
	            gghGbiaozhun.addFee(CostCode._300014, elements.get(12).text());
	            gghGbiaozhun.addFee(CostCode._300015, elements.get(13).text());
	            gghGbiaozhun.addFee(CostCode._300016, elements.get(14).text());
	            gghGbiaozhun.addFee(CostCode._300020, elements.get(15).text());
	            gghGbiaozhun.addFee(CostCode._300017, elements.get(16).text());
	            gghGbiaozhun.addFee(CostCode._300008, elements.get(17).text());
	            gghGbiaozhun.addFee(CostCode._300007, elements.get(18).text());
	            gghGbiaozhun.addFee(CostCode._300009, elements.get(19).text());
	            gghGbiaozhun.addFee(CostCode._300021, elements.get(20).text());
	            gghGbiaozhun.addFee(CostCode._300022, elements.get(21).text());
	            gghGbiaozhun.addFee(CostCode._300023, elements.get(22).text());
	            gghGbiaozhun.addFee(CostCode._300024, elements.get(23).text());
	            gghGbiaozhun.addFee(CostCode._300025, elements.get(24).text());
	            gghGbiaozhun.addFee(CostCode._300026, elements.get(25).text());
	            gghGbiaozhun.setOutTime("");
	            gghGbiaozhun.setStorageDays(elements.get(35).text());
	            gghGbiaozhun.setResult("success");
	        }
	        if(gghGbiaozhun==null) {
	        	gghGbiaozhun = new GGHGbiaozhun();
	        	gghGbiaozhun.setContainerNo(gghGbiaozhunDto.getContainerNo());
	        	gghGbiaozhun.setLadingBillNo(gghGbiaozhunDto.getLadingBillNo());
	        	gghGbiaozhun.setPortNo(gghGbiaozhunDto.getPortNo());
	        	gghGbiaozhun.setId(gghGbiaozhunDto.getId());
	        	gghGbiaozhun.setResult("fail");
	        }
	        result.add(gghGbiaozhun);
        }
        return result;
    }

    /**
     * 远海码头标准费用查询
     *
     * @param yhjzXbiaozhunDto
     * @return
     */
    private List<Object> YHJZXbiaozhun( List<YHJZXbiaozhunDto> yhjzXbiaozhunDtoList) {
    	  List<Object> result = new ArrayList<>();       
    	 if(yhjzXbiaozhunDtoList.isEmpty()) {
 			return result;
 		}
    	Session session = Requests.session();
    	for(YHJZXbiaozhunDto yhjzXbiaozhunDto : yhjzXbiaozhunDtoList) {
    		String url = String.format(UrlUtil.YHJZXBIAOZHUN, yhjzXbiaozhunDto.getLadingBillNo(), yhjzXbiaozhunDto.getContainerNo());
	        String dxResult = session.get(url).body().send().toTextResponse().getBody();
	        Document dxDocument = Jsoup.parse(dxResult);
	        Element table = dxDocument.getElementById("totalTable");
	        Elements tr = table.getElementsByTag("tr");      
	        YHJZXbiaozhun yhjzXbiaozhun = null;
	        for (int i = 1; i < tr.size(); i++) {
	            Elements elements = tr.get(i).getElementsByTag("td");
	            if(elements.get(0).text().equals(yhjzXbiaozhunDto.getLadingBillNo())) {
	            	yhjzXbiaozhun = new YHJZXbiaozhun();
	            	yhjzXbiaozhun.setId(yhjzXbiaozhunDto.getId());
		            yhjzXbiaozhun.setLadingBillNo(elements.get(0).text());
		            yhjzXbiaozhun.setContainerNo(elements.get(1).text());
//		            yhjzXbiaozhun.setXiangxing(elements.get(2).text());
//		            yhjzXbiaozhun.setJinchukou(elements.get(3).text());
		            yhjzXbiaozhun.addFee(CostCode._300001, elements.get(4).text());	            
		            yhjzXbiaozhun.addFee(CostCode._300002, elements.get(5).text());
		            yhjzXbiaozhun.addFee(CostCode._300003, elements.get(6).text());
		            yhjzXbiaozhun.addFee(CostCode._300006, elements.get(7).text());
		            yhjzXbiaozhun.addFee(CostCode._300028, elements.get(8).text());
		            yhjzXbiaozhun.addFee(CostCode._300017, elements.get(9).text());
		            String inDate=elements.get(14).text();
	    			String outDate=elements.get(15).text();
	    			yhjzXbiaozhun.setOutDate(outDate);
	    			
					yhjzXbiaozhun.setStorageDays(storageDays(inDate,outDate));
	    			yhjzXbiaozhun.setTotalFee(elements.get(10).text());
	    			yhjzXbiaozhun.setResult("success");
	            }
	        }
        if(yhjzXbiaozhun==null) {
        	yhjzXbiaozhun = new YHJZXbiaozhun();
        	yhjzXbiaozhun.setContainerNo(yhjzXbiaozhunDto.getContainerNo());
        	yhjzXbiaozhun.setLadingBillNo(yhjzXbiaozhunDto.getLadingBillNo());
        	yhjzXbiaozhun.setPortNo(yhjzXbiaozhunDto.getPortNo());
        	yhjzXbiaozhun.setId(yhjzXbiaozhunDto.getId());
        	yhjzXbiaozhun.setResult("fail");
        }
        result.add(yhjzXbiaozhun);
    	}
	        
    	return result;
    }

    /**
     * 海天 查询 费用
     * 箱号containerId必填
     *
     * @param htrtFee
     * @return
     */
    private List<Object> htSearch(List<HTRTFeeDto> htrtFeeList) {
    	 List<Object> result = new ArrayList<>();
    	 if(htrtFeeList.isEmpty()) {
 			return result;
 		}
    	 HTRTFeeDto htrtFeeDto = null;
    	 for(HTRTFeeDto htrtFee : htrtFeeList) {
	        Session session = Requests.session();
	        String pass = LoginUtil.getXHCTJsTicket(session, LoginParamsDto.getLoginParams(UrlUtil.XHCTDEFAULT, UrlUtil.XHCTVALIDATE, null, null));
	        Map<String, Object> param = new HashMap<>();
		        param.put("DataSource", "XHCT");
		        param.put("queryType", 0);
		        param.put("sortname", "CONID");
		        param.put("sortorder", "desc");
		        param.put("changepage", false);
		        param.put("dataPrivilege", false);    
		        String TFEEview = AESUtil.xhct("XHCT.TFEE", pass);
		        String encrpyCls1 = AESUtil.xhct("CONID as CONID,VOYAGECODE as VOYAGECODE,IMOREX as IMOREX,to_char(INDATE,'yyyy/mm/dd') as INDATE,to_char(OUTDATE,'yyyy/mm/dd') as OUTDATE", pass);
		        String encrpyCls2 = AESUtil.xhct("*", pass);
	        	param.put("encrpyCls", encrpyCls1);
	 	        param.put("view", TFEEview);
	        	String searchValue = htrtFee.getContainerNo();
		        String json = "{\"op\":\"and\",\"rules\":[{\"field\":\"CONTNO\",\"value\":\"" + searchValue + "\",\"op\":\"equal\"}]}";
		        param.put("encrpyCondition", AESUtil.xhct(json, pass));
		        Response<String> stringResponse = session.post(UrlUtil.XMHTHRFREEQUERY).forms(param).send().toTextResponse();
		        //查询结果
		        String resultBody = stringResponse.getBody();
		        JSONArray rows = JSONObject.parseObject(resultBody).getJSONArray("Rows");
		        
		        if (rows != null && rows.size() > 0) {
		        	List<String> conids = Lists.newArrayList();
		        	if(searchValue.equals(htrtFee.getLadingBillNo())) {
		        		for(int j=0;j<rows.size();j++) {
			        		conids.add(rows.getJSONObject(j).getString("CONID"));//根据提单号查询的话
			        	}
		        	}else {
		        		conids.add(rows.getJSONObject(0).getString("CONID"));//根据箱号查询
		        	}
		        	
		            param.clear();
		            //查询船名
		            param.put("DataSource", "XHCT");
		            param.put("view", TFEEview);
		            json = "{\"op\":\"and\",\"rules\":[{\"field\":\"CONID\",\"value\":\""+StringUtils.join(conids,",")+"\",\"op\":\"in\"}]}";
		            param.put("encrpyCondition", AESUtil.xhct(json, pass));
		            param.put("encrpyCls", encrpyCls2);
		            stringResponse = session.post(UrlUtil.XMHTHRFREEQUERY).forms(param).send().toTextResponse();
		            resultBody = stringResponse.getBody();
		            rows = JSONObject.parseObject(resultBody).getJSONArray("Rows");
		            if (rows != null && rows.size() > 0) {
		            	for (int i=0;i<rows.size();i++) {
		            		JSONObject row = rows.getJSONObject(i);
			                if(row.getString("CONTNO").equals(htrtFee.getContainerNo())&&row.getString("BLNO").contains(htrtFee.getLadingBillNo())) {
			                	htrtFeeDto = new HTRTFeeDto();
			                	htrtFeeDto.setId(htrtFee.getId());
				                htrtFeeDto.setContainerNo(row.getString("CONTNO"));
				                //字母O
				                htrtFeeDto.setLadingBillNo(row.getString("BLNO"));
				                htrtFeeDto.addFee(CostCode._300001, row.getString("PORTFEE"));
				                htrtFeeDto.addFee(CostCode._300002, row.getString("ADDFEE"));
				                htrtFeeDto.addFee(CostCode._300003, row.getString("STACKFEE"));
				                htrtFeeDto.addFee(CostCode._300030, row.getString("MOVEFEE"));
				                htrtFeeDto.addFee(CostCode._300029, row.getString("CUSMOVEFEE"));//CYZY
				                htrtFeeDto.addFee(CostCode._300004, row.getString("LHLOADFEE"));//LH
				                SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				                htrtFeeDto.setOutDate(sd.format(new Date(Long.parseLong(row.getString("OUTDATE").substring(6,19)))));
				                htrtFeeDto.setResult("success");
				                String inDate=row.getString("INDATE");
				    			String outDate=row.getString("OUTDATE");
				                htrtFeeDto.setStorageDays(computeStorageDays(inDate,outDate));
				                htrtFeeDto.setPortNo(DockCode._HTD);
				                htrtFeeDto.setTotal(row.getString("TOTAL"));
					            LOGGER.info(htrtFeeDto.toString());	            
				            }
			        	}
		            }
		        }
		        if(htrtFeeDto==null) {
		        	htrtFeeDto = new HTRTFeeDto();
		        	htrtFeeDto.setContainerNo(htrtFee.getContainerNo());
		        	htrtFeeDto.setLadingBillNo(htrtFee.getLadingBillNo());
		        	htrtFeeDto.setPortNo(htrtFee.getPortNo());
		        	htrtFeeDto.setId(htrtFee.getId());
		        	htrtFeeDto.setResult("fail");
		        }
		        result.add(htrtFeeDto);
	        }
        
        return result;
    }

    /**
     * 海润  查询 费用
     * 箱号containerId必填
     *
     * @param htrtFee
     * @return
     */
    private List<Object> hrSearch(List<HTRTFeeDto> htrtFeeList) {
        List<Object> result = new ArrayList<>();
        if(htrtFeeList.isEmpty()) {
			return result;
		}
        HTRTFeeDto htrtFeeDto = null;
        for(HTRTFeeDto htrtFee: htrtFeeList) {
        Session session = Requests.session();
	        Map<String, Object> param = new HashMap<>();
		        param.put("DataSource", "HC");
		        param.put("queryType", 0);
		        param.put("sortname", "CONID");
		        param.put("sortorder", "desc");
		        param.put("changepage", false);
		        param.put("dataPrivilege", false);	        //箱号
		        String pass = LoginUtil.getXHCTJsTicket(session, LoginParamsDto.getLoginParams(UrlUtil.XHCTDEFAULT, UrlUtil.XHCTVALIDATE, null, null));
		        String TFEEview = AESUtil.xhct("hc_xhct.TFEE", pass);
		        String encrpyCls1 = AESUtil.xhct("CONID as CONID,VOYAGECODE as VOYAGECODE,IMOREX as IMOREX,to_char(INDATE,'yyyy/mm/dd') as INDATE,to_char(OUTDATE,'yyyy/mm/dd') as OUTDATE", pass);
		        String encrpyCls2 = AESUtil.xhct("*", pass);
	        	param.put("view", TFEEview);
	        	param.put("encrpyCls", encrpyCls1);
	        	String searchValue = htrtFee.getContainerNo();
	  	        String json = "{\"op\":\"and\",\"rules\":[{\"field\":\"CONTNO\",\"value\":\"" + searchValue + "\",\"op\":\"equal\"}]}";
	  	        param.put("encrpyCondition", AESUtil.xhct(json, pass));
	  	        Response<String> stringResponse = session.post(UrlUtil.XMHTHRFREEQUERY).forms(param).send().toTextResponse();
	  	        //查询结果
	  	        String resultBody = stringResponse.getBody();
	  	        JSONArray rows = JSONObject.parseObject(resultBody).getJSONArray("Rows");
	  	        
	  	        if (rows != null && rows.size() > 0) {
	  	        	List<String> conids = Lists.newArrayList();
	  	        	if(searchValue.equals(htrtFee.getLadingBillNo())) {
		        		for(int j=0;j<rows.size();j++) {
			        		conids.add(rows.getJSONObject(j).getString("CONID"));//根据提单号查询的话
			        	}
		        	}else {
		        		conids.add(rows.getJSONObject(0).getString("CONID"));//根据箱号查询
		        	}
	  	        	param.remove("queryType");
	  	            param.remove("sortname");
	  	            param.remove("changepage");
	  	            param.remove("dataPrivilege");
	  	            param.put("encrpyCls", encrpyCls2);  
	  	            json = "{\"op\":\"and\",\"rules\":[{\"field\":\"CONID\",\"value\":" + StringUtils.join(conids,",") + ",\"op\":\"in\"}]}";
	  	            param.put("encrpyCondition", AESUtil.xhct(json, pass));
	  	            stringResponse = session.post(UrlUtil.XMHTHRFREEQUERY).forms(param).send().toTextResponse();
	  	            //查询结果
	  	            resultBody = stringResponse.getBody();
	  	            rows = JSONObject.parseObject(resultBody).getJSONArray("Rows");
	  	            if (rows != null && rows.size() > 0) {
	  	            	for (int i=0;i<rows.size();i++) {
	  	            		JSONObject row = rows.getJSONObject(i);
		  	                if(row.getString("CONTNO").equals(htrtFee.getContainerNo())
		  	                		&&row.getString("BLNO").contains(htrtFee.getLadingBillNo())) {
		  	                	htrtFeeDto = new HTRTFeeDto();
		  	                	htrtFeeDto.setId(htrtFee.getId());
		  		                htrtFeeDto.setContainerNo(row.getString("CONTNO"));
		  		                //字母O
		  	
		  		                htrtFeeDto.setLadingBillNo(row.getString("BLNO"));
		  		                htrtFeeDto.addFee(CostCode._300001, row.getString("PORTFEE"));
		  		                htrtFeeDto.addFee(CostCode._300002, row.getString("ADDFEE"));
		  		                htrtFeeDto.addFee(CostCode._300003, row.getString("STACKFEE"));
		  		                htrtFeeDto.addFee(CostCode._300030, row.getString("MOVEFEE"));
		  		                htrtFeeDto.addFee(CostCode._300029, row.getString("CUSMOVEFEE"));
		  		                htrtFeeDto.addFee(CostCode._300004, row.getString("LHLOADFEE"));
		  		                SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");		                
		  		                htrtFeeDto.setOutDate(sd.format(new Date(Long.parseLong(row.getString("OUTDATE").substring(6,19)))));
		  		                htrtFeeDto.setResult("success");
		  		                String inDate=row.getString("INDATE");
		  		    			String outDate=row.getString("OUTDATE");
		  		                htrtFeeDto.setStorageDays(computeStorageDays(inDate,outDate));
		  		                htrtFeeDto.setPortNo(DockCode._HRD);
		  		                htrtFeeDto.setTotal(row.getString("TOTAL"));
		  		                LOGGER.info(htrtFeeDto.toString());
		  		            }
			        	}
	  	            }
	  	        }
	  	        if(htrtFeeDto==null){
	  	        	htrtFeeDto =new HTRTFeeDto();
	              	htrtFeeDto.setContainerNo(htrtFee.getContainerNo());
	              	htrtFeeDto.setLadingBillNo(htrtFee.getLadingBillNo());
	              	htrtFeeDto.setPortNo(htrtFee.getPortNo());
	              	htrtFeeDto.setId(htrtFee.getId());
	              	htrtFeeDto.setResult("fail");		             
	              }
	  	      result.add(htrtFeeDto);
	        }
	        return result;
    }

    /**
     * 嵩屿码头 拖车费用查询
     * boxNumber 箱号必填
     *
     * @param tuoche
     * @return
     */
    private List<Object> sytuoche(List<SYTuocheDto> tuocheList) {
	   	 List<Object> result = new ArrayList<>();
		 if(tuocheList.isEmpty()) {
				return result;
			}
		 Session session = Requests.session();
		 String[] queryParams = new String[]{
	             "__VIEWSTATE",
	             "__VIEWSTATEGENERATOR",
	             "__EVENTVALIDATION"
	     };
        for(SYTuocheDto tuoche:tuocheList) {
            Response<String> stringResponse = session.get(UrlUtil.XSCTTU0CHE).send().toTextResponse();
        	Map<String, Object> queryMap = new HashMap<>();
            Document document = Jsoup.parse(stringResponse.getBody());
            Element form = document.getElementById("form1");
            Elements inputs = form.getElementsByTag("input");
            for (Element input: inputs) {
                String name = input.attr("name");
                String value = input.attr("value");
                if (Arrays.asList(queryParams).contains(name)) {
                    queryMap.put(name, value);
                }
            }
            queryMap.put("choice", 2);
            queryMap.put("choice", 1);
            queryMap.put("v_type", "d");
            queryMap.put("scope", "k");
            queryMap.put("TextBox4", "MRKU1101302");
            queryMap.put("Button5", "维护前查询");
            for (Map.Entry<String, Object> entry: queryMap.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue().toString();
                System.out.println("key=" + key + " value=" + value);
            }
            SYTuocheDto syTuocheDto = null;
    	        stringResponse = session.get(UrlUtil.XSCTTUOCHEFEE +tuoche.getLadingBillNo()+"&cn="+ tuoche.getContainerNo()).forms(queryMap).send().toTextResponse();
    	        document = Jsoup.parse(stringResponse.getBody());
    	        Element table = document.getElementById("GridView1");
    	        Elements trs = table.getElementsByTag("tr");
    	        int i = 0;
    	        
    	        for (Element tr: trs) {
    	            if (i < 2) {
    	                i++;
    	                continue;
    	            }
    	            Elements td = tr.getElementsByTag("td");
    	            if(tuoche.getLadingBillNo()!=null&&!td.get(6).text().contains(tuoche.getLadingBillNo())) {
    	            	continue;
    	            }
    	            syTuocheDto = new SYTuocheDto(
    	            		tuoche.getId(),
    	                    td.get(0).text(),
    	                    td.get(1).text(),
    	                    td.get(2).text(),
    	                    td.get(3).text(),
    	                    td.get(4).text(),
    	                    td.get(5).text(),
    	                    td.get(6).text(),
    	                    td.get(7).text(),
    	                    td.get(8).text(),
    	                    td.get(9).text(),                    
    	                    td.get(10).text(),
    	                    td.get(11).text(),
    	                    td.get(12).text(),
    	                    td.get(13).text(),
    	                    td.get(14).text(),
    	                    td.get(15).text(),
    	                    td.get(16).text(),
    	                    td.get(17).text(),
    	                    td.get(18).text(),
    	                    td.get(19).text(),
    	                    td.get(20).text(),
    	                    td.get(21).text(),
    	                    td.get(22).text(),
    	                    td.get(23).text(),
    	                    td.get(24).text(),
    	                    td.get(25).text(),                    
    	                    td.get(26).text()
    	            );
    	            result.add(syTuocheDto);
    	        }
            if(syTuocheDto==null) {
            	syTuocheDto = new SYTuocheDto();
            	syTuocheDto.setContainerNo(tuoche.getContainerNo());
            	syTuocheDto.setLadingBillNo(tuoche.getLadingBillNo());
            	syTuocheDto.setPortNo(tuoche.getPortNo());
            	syTuocheDto.setId(tuoche.getId());
            	syTuocheDto.setResult("fail");
            	result.add(syTuocheDto);
            }
        }
        return result;
        
    }

    class SearchThread<T> implements Runnable{
    	private List<T> parametersDtos; 
    	private int type;
    	private Vector<Object> result; 
    	private CountDownLatch cd; 
    	public SearchThread(List<T> parametersDtos,
    			Vector<Object> result,
    			int type,
    			CountDownLatch cd) {
    		this.parametersDtos = parametersDtos;
    		this.result = result;
    		this.type = type;
    		this.cd = cd;
    	}
		@Override
		public void run() {
			try {
				if(type==1) {
					GJHGCostSpider a = new GJHGCostSpider();	    			
		    		result.addAll(a.startCrawl((List<CostParametersDto>)parametersDtos));
				}else if(type==2) {
					result.addAll(GGHGbiaozhun((List<GGHGbiaozhunDto>)parametersDtos));	
				}else if(type==3) {
					result.addAll(hrSearch((List<HTRTFeeDto>)parametersDtos));	
				}else if(type==4) {
					result.addAll(htSearch((List<HTRTFeeDto>)parametersDtos));	
				}else if(type==5) {
					result.addAll(sytuoche((List<SYTuocheDto>)parametersDtos));	
				}else if(type==6) {
					result.addAll(YHJZXbiaozhun((List<YHJZXbiaozhunDto>)parametersDtos));	
				}
			}catch (Exception e) {
			}
			this.cd.countDown();
		}
    }
    
    private void buildSearch(List<CostParametersDto> costParametersDtoList,
    		List<CostParametersDto> _costParametersDtoList,
    		List<GGHGbiaozhunDto> _gghGbiaozhunDtoList,
    		List<HTRTFeeDto> _htrtFeeDtoList_HRD,
    		List<HTRTFeeDto> _htrtFeeDtoList_HTD,
    		List<SYTuocheDto> _syTuocheDtoList,
    		List<YHJZXbiaozhunDto> _yhjzXbiaozhunDtoList,
    		List<TerminalCostDto> _terminalCostDtoList
    		) {
    	for(CostParametersDto costParametersDto:costParametersDtoList) {
    		if(costParametersDto.getPortNo()!=null) {    			
        		if(costParametersDto.getPortNo().equals(DockCode._HC)) {
        			//登入情况下查询
        			if(!costParametersDto.getUsername().isEmpty()&&!costParametersDto.getPwd().isEmpty()) {
        				_costParametersDtoList.add(costParametersDto);
        			}else {
        				//未登入情况下查询
    	    			GGHGbiaozhunDto gghGbiaozhunDto = new GGHGbiaozhunDto();
    	    			gghGbiaozhunDto.setContainerNo(costParametersDto.getContainerNo());
    	    			gghGbiaozhunDto.setLadingBillNo(costParametersDto.getLadingBillNo());
    	    			gghGbiaozhunDto.setPortNo(costParametersDto.getPortNo());
    	    			gghGbiaozhunDto.setId(costParametersDto.getId());
    	    			_gghGbiaozhunDtoList.add(gghGbiaozhunDto);
        			}	    			
        		}else if(costParametersDto.getPortNo().equals(DockCode._HRD))  {
        			HTRTFeeDto htrtFeeDto =new HTRTFeeDto();
        			htrtFeeDto.setContainerNo(costParametersDto.getContainerNo());
        			htrtFeeDto.setLadingBillNo(costParametersDto.getLadingBillNo());
        			htrtFeeDto.setPortNo(costParametersDto.getPortNo());
        			htrtFeeDto.setId(costParametersDto.getId());
        			_htrtFeeDtoList_HRD.add(htrtFeeDto);
        		}else if(costParametersDto.getPortNo().equals(DockCode._HTD)) {
        			HTRTFeeDto htrtFeeDto =new HTRTFeeDto();
        			htrtFeeDto.setContainerNo(costParametersDto.getContainerNo());
        			htrtFeeDto.setLadingBillNo(costParametersDto.getLadingBillNo());
        			htrtFeeDto.setPortNo(costParametersDto.getPortNo());
        			htrtFeeDto.setId(costParametersDto.getId());
        			_htrtFeeDtoList_HTD.add(htrtFeeDto);
        		}else if(costParametersDto.getPortNo().equals(DockCode._SYT)) {
        			SYTuocheDto syTuocheDto = new SYTuocheDto();
        			syTuocheDto.setContainerNo(costParametersDto.getContainerNo());
        			syTuocheDto.setLadingBillNo(costParametersDto.getLadingBillNo());
        			syTuocheDto.setPortNo(costParametersDto.getPortNo());
        			syTuocheDto.setId(costParametersDto.getId());
        			_syTuocheDtoList.add(syTuocheDto);
        		}else if(costParametersDto.getPortNo().equals(DockCode._YHT)) {
        			YHJZXbiaozhunDto yhjzXbiaozhunDto = new YHJZXbiaozhunDto();
        			yhjzXbiaozhunDto.setContainerNo(costParametersDto.getContainerNo());
        			yhjzXbiaozhunDto.setLadingBillNo(costParametersDto.getLadingBillNo());
        			yhjzXbiaozhunDto.setPortNo(costParametersDto.getPortNo());
        			yhjzXbiaozhunDto.setId(costParametersDto.getId());
        			_yhjzXbiaozhunDtoList.add(yhjzXbiaozhunDto);
        		}else {
        			TerminalCostDto terminalCostDto = new TerminalCostDto();
        			terminalCostDto.setContainerNo(costParametersDto.getContainerNo());
        			terminalCostDto.setLadingBillNo(costParametersDto.getLadingBillNo());
        			terminalCostDto.setPortNo(costParametersDto.getPortNo());
        			terminalCostDto.setId(costParametersDto.getId());
        			terminalCostDto.setResult("fail");
        			_terminalCostDtoList.add(terminalCostDto);
        		}
    		}else {
    			TerminalCostDto terminalCostDto = new TerminalCostDto();
    			terminalCostDto.setContainerNo(costParametersDto.getContainerNo());
    			terminalCostDto.setLadingBillNo(costParametersDto.getLadingBillNo());
    			terminalCostDto.setPortNo(costParametersDto.getPortNo());
    			terminalCostDto.setId(costParametersDto.getId());
    			terminalCostDto.setResult("fail");
    			_terminalCostDtoList.add(terminalCostDto);
    		}
    	}
	
    }
    /** 堆存天数
     * 
     * @param inDate
     * @param outDate
     * @return
     */
    private String storageDays(String inDate, String outDate) {
		if(inDate==null||!inDate.matches("\\d{4,}-\\d{2,}-\\d{2,}")) return "0";
		if(outDate==null||!outDate.matches("\\d{4,}-\\d{2,}-\\d{2,}")) outDate=DateUtils.getStringDateShort();
		//2017-12-12 ~ 2017-12-12 算1天
		int days=Integer.valueOf(DateUtils.getTwoDay(outDate,inDate))+1;
		return String.valueOf(days);
	}

}
